package procTest;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.logging.Handler;
import java.util.logging.Logger;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import proc.BasicFileProcessor;
import proc.BasicFileWrap;
import proc.BasicMFP;
import proc.FileProcessor;
import proc.FileWrap;

public class BasicMFPTest {

	
	private FileProcessor fileProcTest;
	private File report;
	private File result;
	private final String path = "src/procTest/IOFiles/";
	private Logger LOG;

	@Before
	public void setUp(){
		LOG = Logger.getLogger("");
		report = new File(path+"report_output");
		result = new File(path+"result_output");
		report.delete();
		result.delete();
	}


	/**
	 * All input files are good
	 */
	// TODO
	@Test
	public void auxNormTest() {
		System.out.println("auxNormTest");
		String[] fileNames = { path+"primary_input", path+"auxiliary_input",
				path+"result_output", path+"report_output" };
		BasicMFP.main(fileNames);
		File result = new File(path+"result_output");
		File report = new File(path+"report_output");
		assertEquals("result output file doesn't exist.", true, result.exists());
		assertEquals("report output file doesn't exist.", true, report.exists());
	}

	/**
	 * Your program should properly handle input files (both primary and
	 * auxiliary) of any size, from the empty file to very large graphic image
	 * files. What are your program's internal memory requirements if there are
	 * many millions of bytes between next-line markers? (The internal memory
	 * requirement should be quite small.)
	 */

	// Tests for the result output files
	/**
	 * The result file should contain less than 80 bytes
	 * 
	 * @throws IOException
	 */
	@Test
	public void resultBytesTest() throws IOException {
		System.out.println("resultBytesTest");
		int byteNum = 0;
		String[] fileNames = { path+"primary_input", path+"auxiliary_input",
				path+"result_output", path+"report_output" };
		BasicMFP.main(fileNames);
		FileInputStream resultStream = new FileInputStream(path+"result_output");
		int next = resultStream.read();
		while (next != -1) {
			if (next < 32 && next > 126) {
				byteNum++;
			}
			next = resultStream.read();
		}
		resultStream.close();
		assertEquals("The result file contains more than 80 bytes.", true,
				byteNum <= 80);
	}

	/**
	 * The result file should contain less than 80 bytes when the primary input
	 * is extremely large
	 * 
	 * @throws IOException
	 */
	@Test
	public void resultBytesExtTest1() throws IOException {
		System.out.println("resultBytesExtTest1");
		int byteNum = 0;
		String[] fileNames = { path+"primary_input_extreme", path+"auxiliary_input",
				path+"result_output", path+"report_output" };
		BasicMFP.main(fileNames);
		FileInputStream resultStream = new FileInputStream(path+"result_output");
		int next = resultStream.read();
		while (next != -1) {
			if (next < 32 && next > 126) {
				byteNum++;
			}
			next = resultStream.read();
		}

		assertEquals("The result file contains more than 80 bytes.", true,
				byteNum <= 80);
	}

	/**
	 * The result file should contain less than 80 bytes when both the primary
	 * and auxiliary input files are large
	 * 
	 * @throws IOException
	 */
	@Test
	public void resultBytesExtTest2() throws IOException {
		System.out.println("resultBytesExtTest2");
		int byteNum = 0;
		String[] fileNames = { path+"primary_input_extreme",
				path+"auxiliary_input_large", path+"result_output", path+"report_output" };
		BasicMFP.main(fileNames);
		FileInputStream resultStream = new FileInputStream(path+"result_output");
		int next = resultStream.read();
		while (next != -1) {
			if (next < 32 && next > 126) {
				byteNum++;
			}
			next = resultStream.read();
		}

		assertEquals("The result file contains more than 80 bytes.", true,
				byteNum <= 80);
	}

	/**
	 * The result file should only contain printable bytes
	 * 
	 * @throws IOException
	 */
	@Test
	public void resultPritTest() throws IOException {
		System.out.println("resltPritTest");
		boolean result = true;
		String[] fileNames = { path+"primary_input", path+"auxiliary_input",
				path+"result_output", path+"report_output" };
		BasicMFP.main(fileNames);
		FileInputStream resultStream = new FileInputStream(path+"result_output");
		int next = resultStream.read();
		while (next != -1) {
			if (next < 32 && next > 126) {
				result = false;
			}
			next = resultStream.read();
		}
		assertEquals("The result file contains bytes not printable.", true,
				result);
	}

	/**
	 * The result file should contain num_lines lines of the primary input file
	 * 
	 * @throws IOException
	 */
	@Test
	public void resultLineTest() throws IOException {
		System.out.println("resultLineTest");
		int lineNum = 0;
		String[] fileNames = { path+"primary_input", path+"auxiliary_input",
				path+"result_output", path+"report_output" };
		BasicMFP.main(fileNames);
		File result = new File(path+"result_output");
		BufferedReader br = new BufferedReader(new InputStreamReader(
				new FileInputStream(result)));
		int c;
		while ((c = br.read()) != -1) {
			if (c == '\n') {
				lineNum++;
			}
		}
		this.fileProcTest = new BasicFileProcessor(this.LOG);
		File auxFile = new File(path+"auxiliary_input");
		assertEquals("The result file contains more than num_lines.",
				this.fileProcTest.processAuxFile(auxFile), lineNum);
	}

	/**
	 * The result file should contain num_lines lines of the primary input file
	 * when the input file is extremely large
	 * 
	 * @throws IOException
	 */
	@Test
	public void resultLineExtTest() throws IOException {
		System.out.println("resultLineExtTest");
		int lineNum = 0;
		String[] fileNames = { path+"primary_input_extreme",
				path+"auxiliary_input_large", path+"result_output", path+"report_output" };
		BasicMFP.main(fileNames);
		File result = new File(path+"result_output");
		BufferedReader br = new BufferedReader(new InputStreamReader(
				new FileInputStream(result)));
		int c;
		while ((c = br.read()) != -1) {
			if (c == '\n') {
				lineNum++;
			}
		}
		this.fileProcTest = new BasicFileProcessor(this.LOG);
		File auxFile = new File(path+"auxiliary_input_large");
		assertEquals("The result file contains more than num_lines.",
				this.fileProcTest.processAuxFile(auxFile), lineNum);
	}

	/**
	 * The result file should contain only one line
	 */
	// TODO

	/**
	 * The result file should contain only one line when the input file is
	 * extremely large
	 * @throws InterruptedException 
	 */
	// TODO

	@After
	public void deleteOuput() throws SecurityException, InterruptedException {
		LOG=null;
		
	}
}
